# pragma once

# include "cpp_tools_Headers.h"
# include "FileCheck.h"

namespace cpp_tools
{
    /// @brief 从CSV文件读取Eigen矩阵
    /// @param fileName 
    /// @return 
    Eigen::MatrixXd csvRead(const std::string& fileName) {
        std::ifstream inFile(fileName);
        if (!inFile.is_open()) {
            std::cerr << "csvRead: 无法打开文件: " << fileName << std::endl;
            return Eigen::MatrixXd(0, 0); // 返回空矩阵
        }

        std::vector<std::vector<double>> data;
        std::string line;

        while (std::getline(inFile, line)) {
            std::vector<double> row;
            std::stringstream ss(line);
            std::string cell;

            while (std::getline(ss, cell, ',')) {
                row.push_back(std::stod(cell));
            }
            data.push_back(row);
        }

        inFile.close();

        // 将数据转换为Eigen矩阵
        int rows = data.size();
        int cols = data[0].size();
        Eigen::MatrixXd matrix(rows, cols);

        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                matrix(i, j) = data[i][j];
            }
        }

        return matrix;
    }

    /// @brief 写入到.csv文件
    /// @param fileName 
    /// @param matrix 
    /// @param decimal 保留的小数点位数, -1 表示不使用固定小数点位数
    /// @return -1：写入失败；0：写入成功
    int csvWrite(const std::string& fileName, const Eigen::MatrixXd& matrix, const int decimal = -1) {
        if (!std::filesystem::exists(fileName));
        {
            std::filesystem::path dirPath = std::filesystem::path(fileName).parent_path();
            
            // 如果目录不存在，则创建目录
            if (!std::filesystem::exists(dirPath)) {
                if (std::filesystem::create_directories(dirPath)) {
                    // std::cout << "目录创建成功: " << dirPath << std::endl;
                } else {
                    std::cerr << "目录创建失败: " << dirPath << std::endl;
                    return -1;
                }
            }
        }

        std::ofstream outFile(fileName);
        if (!outFile.is_open()) {
            std::cerr << "csvWrite: 无法打开文件: " << fileName << std::endl;
            return -1;
        }

        for (int i = 0; i < matrix.rows(); ++i) {
            for (int j = 0; j < matrix.cols(); ++j) {
                if (decimal == -1)
                {
                    outFile << matrix(i, j);
                }
                else if (decimal > 0)
                {
                    outFile << std::fixed << std::setprecision(decimal) << matrix(i, j);
                }
                else
                {
                    throw std::range_error("非法精度: " + std::to_string(decimal));
                }
                
                if (j < matrix.cols() - 1) {
                    outFile << ","; // 字段之间用逗号分隔
                }
            }
            outFile << "\n"; // 每一行结束后换行
        }

        outFile.close();
        std::cout << "csvWrite: 数据已成功写入文件: " << fileName << std::endl;
        
        return 0;
    }

    class csvRecorder
    {
    protected:
        std::string fileName;
        int decimal = 8;

        std::ofstream outFile;
    public:
        /// @brief 以矩阵的形式记录数据，每次存储一个行向量，按列存储
        /// @param arg1 每个数据的长度
        csvRecorder(std::string fileName)
            : fileName(fileName)
        {
            checkFile(fileName, true);

            outFile = std::ofstream(fileName);
        };

        ~csvRecorder()
        {
            outFile.close();
        };

        /// @brief 记录一个数据
        /// @param newData 
        void record(Eigen::VectorXd newData)
        {
            for (int i = 0; i < newData.size(); ++i) {
                if (decimal == -1)
                {
                    outFile << newData(i);
                }
                else if (decimal > 0)
                {
                    outFile << std::fixed << std::setprecision(decimal) << newData(i);
                }
                else
                {
                    throw std::range_error("非法精度: " + std::to_string(decimal));
                }
                
                if (i < newData.size() - 1) {
                    outFile << ","; // 字段之间用逗号分隔
                }
            }

            outFile << "\n"; // 每一行结束后换行
        };
    };
} // namespace cpp_tools

